package com.itlong.cloud.controller;

import com.itlong.cloud.POJO.DTO.app.AppUploadPassRecordDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardFaceSyncDataGetPageDTO;
import com.itlong.cloud.POJO.PO.ProjectPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.AppPadDeviceVO;
import com.itlong.cloud.POJO.VO.smartcard.SmartCardIncrementUpdateGetVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.annotation.UnAuthAccessRequired;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.enumerate.ecode.AppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.SmartCardErrorCodeEnum;
import com.itlong.cloud.equip.app.IAppDeviceServiceClient;
import com.itlong.cloud.equip.commons.ICloudEntranceServiceClient;
import com.itlong.cloud.equip.property.ICloudIntercomServiceClient;
import com.itlong.cloud.equip.property.IPadFaceSyncDataServiceClient;
import com.itlong.cloud.equip.smartcard.ISmartCardFaceServiceClient;
import com.itlong.cloud.iottp.IIotServerServiceClient;
import com.itlong.cloud.project.app.IAppProjectServiceClient;
import com.itlong.cloud.project.operate.IOperateProjectServiceClient;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.app.IAppHomeServiceClient;
import com.itlong.cloud.user.app.IAppPadFaceServiceClient;
import com.itlong.cloud.user.smartcard.ISmartCardUserInfoServiceClient;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * <desc>
 *      一卡通动态人脸识别控制器
 * <desc/>
 *
 * @createDate 2019/03/18
 */
@RestController
@RequestMapping("/smartCard")
@RefreshScope
public class SmartCardFaceController {

    private static final Logger LOG = LoggerFactory.getLogger(SmartCardFaceController.class);

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;
    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;
    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;
    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;
    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    @Autowired
    IAppPadFaceServiceClient iAppPadFaceServiceClient;

    @Autowired
    ICloudIntercomServiceClient iCloudIntercomServiceClient;

    @Autowired
    ISmartCardUserInfoServiceClient iSmartCardUserInfoServiceClient;

    @Autowired
    ISmartCardFaceServiceClient iSmartCardFaceServiceClient;

    @Autowired
    IAppDeviceServiceClient iAppDeviceServiceClient;

    @Autowired
    IAppHomeServiceClient iAppHomeServiceClient;

    @Autowired
    IPadFaceSyncDataServiceClient iPadFaceSyncDataServiceClient;

    @Autowired
    IOperateProjectServiceClient iOperateProjectServiceClient;

    @Autowired
    ICloudEntranceServiceClient iCloudEntranceServiceClient;

    @Autowired
    IIotServerServiceClient iIotServerServiceClient;

    @Autowired
    IAppProjectServiceClient iAppProjectServiceClient;

    @Autowired
    private RedisService redisService;
    @Value("${" + PlatformConstants.SMART_CARD_TOKEN_KEY + "}")
    String userTokenKey;

    /**
     * <desc>
     *      上传通行记录
     * <desc/>
     *
     * @param appUploadPassRecordDTO 设备类型；1为梯控，2门禁
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/03/18
     */
    @PostMapping(path = "/uploadPassRecord")
    @ResponseBody
    public MessageVO uploadPassRecord(AppUploadPassRecordDTO appUploadPassRecordDTO) {
        try {
            //判断必要信息是否为空
            if (appUploadPassRecordDTO == null || StringUtils.isBlank(appUploadPassRecordDTO.getImageStr()) || StringUtils.isBlank(appUploadPassRecordDTO.getImageType())
                    || StringUtils.isBlank(appUploadPassRecordDTO.getPassTime()) || StringUtils.isBlank(appUploadPassRecordDTO.getType())
                    || StringUtils.isBlank(appUploadPassRecordDTO.getUId()) || StringUtils.isBlank(appUploadPassRecordDTO.getDeviceId())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            AppPadDeviceVO appPadDeviceVO = iAppPadFaceServiceClient.getDeviceUnique(appUploadPassRecordDTO.getType(), appUploadPassRecordDTO.getProjectId(),
                    appUploadPassRecordDTO.getDeviceId());
            appUploadPassRecordDTO.setDeviceUnique(appPadDeviceVO.getDeviceUnique());
            appUploadPassRecordDTO.setDeviceName(appPadDeviceVO.getDeviceName());
            String uploadFilePath = uploadImageFile(appUploadPassRecordDTO.getImageStr(), appUploadPassRecordDTO.getImageType(), FileCatalogEnum.FACE_PASS_FILE);
            if (StringUtils.isNotBlank(uploadFilePath)) {
                appUploadPassRecordDTO.setUploadFilePath(uploadFilePath);
                iCloudIntercomServiceClient.pushPadFaceRecord(appUploadPassRecordDTO);
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【一卡通动态人脸识别】上传通行记录失败", e);
        }
    }

    /**
     * <desc>
     *      管理中心登录验证(工程人员)
     * <desc/>
     *
     * @param projectId 项目编号
     * @param userName  帐号
     * @param password  登陆密码
     * @param type  密码是否加密类型 0不加密 1加密
     * @return 标准格式化响应结果
     * @author Juguang.S
     * @createDate 2019/03/18
     */
    @PostMapping(path = "/engineerLoginVerify")
    @UnAuthAccessRequired
    @ResponseBody
    public MessageVO engineerLoginVerify(String projectId, String userName, String password,String type) {
        try {
            //判断必要信息是否为空
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(userName) || StringUtils.isBlank(password)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            //判断项目是否存在
            if (iOperateProjectServiceClient.checkProjectExist(projectId) <= 0) {
                return new MessageVO(SmartCardErrorCodeEnum.C_LOGIN_PROJECT_NOT_EXISTS.getErrorCode());
            }
            //判断帐号是否存在
            if (iAppPadFaceServiceClient.engineerLoginExistsVerify(userName) == 0) {
                return new MessageVO(AppErrorCodeEnum.PAD_ENGINEER_NOT_EXISTS.getErrorCode());
            }
            //判断帐号是否管辖该项目
            if (iAppPadFaceServiceClient.engineerLoginProjectVerify(projectId, userName) == 0) {
                return new MessageVO(SmartCardErrorCodeEnum.C_LOGIN_ENGINEER_VERIFY_PROJECT_FAIL.getErrorCode());
            }
            //判断当前项目是否被禁用
            if (iAppPadFaceServiceClient.checkProjectForbidden(projectId) > 0) {
                return new MessageVO(AppErrorCodeEnum.PAD_PROJECT_FORBIDDEN.getErrorCode());
            }
            if(StringUtils.isNotEmpty(type) && type.equals("1")){
                //解密密码
                password = UserTokenUtil.getPassword(password,userTokenKey);
            }

            //判断帐号密码是否正确
            Map<String, String> map = iSmartCardUserInfoServiceClient.engineerLoginVerifyForCFace(projectId, userName, Md5EncryptUtil.md5(password));
            if (map == null) {
                return new MessageVO(AppErrorCodeEnum.PAD_ENGINEER_VERIFY_FAIL.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), map);
        } catch (Exception e) {
            throw new DataAccessException("【C#人脸识别】工程人员登录验证失败", e);
        }
    }

    /**
     * <desc>
     *      C#人脸识别获取全量数据
     * </desc>
     *
     * @param syncDataGetPageDTO    数据传输对象
     * @return
     * @author Juguang.S
     * @createDate 2019/03/18
     */
    @RequestMapping(path = "/pullFull", method = RequestMethod.POST)
    @ResponseBody
    public MessageVO pullFull(SmartCardFaceSyncDataGetPageDTO syncDataGetPageDTO) {
        try {
            if (StringUtils.isEmpty(syncDataGetPageDTO.getProjectId())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), iSmartCardFaceServiceClient.pullFull(syncDataGetPageDTO));
        } catch (Exception e) {
            throw new DataAccessException("【smartCard_pullFull】C#人脸识别获取全量数据失败", e);
        }
    }

    /**
     * <desc>
     *      C#端熠知平板进行呼梯
     * <desc/>
     *
     * @param projectId 项目编号
     * @param deviceId  设备机号
     * @param naturalFloor  呼梯权限标识楼层
     * @return 标准格式化响应结果
     * @author Juguang.S
     * @createDate 2019/03/19
     */
    @PostMapping(path = "/callElevator")
    @ResponseBody
    public MessageVO callElevator(String projectId, String deviceId, String naturalFloor) {
        try {
            //判断必要信息是否为空
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(deviceId) || StringUtils.isBlank(naturalFloor)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String deviceUnique = String.format("%s%s%04d",projectId,"1",Integer.parseInt(deviceId));
            //取真实楼层
            String realFloor = iAppHomeServiceClient.batchGetRealFloorList(deviceUnique, naturalFloor);
            if (StringUtils.isBlank(realFloor)) {
                LOG.info(String.format("【平板_预约呼梯】楼层号信息有误，设备号：%s 楼层：s% ", deviceUnique, naturalFloor));
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode());
            }
            //调取IOT预约呼梯
            iAppDeviceServiceClient.cloudElevatorCall(deviceUnique, CloudElevatorSourceEnum.ITLONG_CLOUD_ELEVATOR.getDescription(), "", "", realFloor,
                    CloudElevatorCallTypeEnum.IN.getType(), null, CallElevatorSourceTypeEnum.APP.getType(),null,null,null, null, null, null, "");

            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【C#人脸识别】呼梯失败", e);
        }
    }

    /**
     * <desc>
     *      C#端IOT开门
     * <desc/>
     *
     * @param projectId 项目编号
     * @param deviceId  设备机号
     * @param userId  人脸识别后的faceId
     * @return 标准格式化响应结果
     * @author Juguang.S
     * @createDate 2019/05/26
     */
    @PostMapping(path = "/netOpenDoor")
    @ResponseBody
    public MessageVO netOpenDoor(String projectId, String deviceId,String userId) {
        try {
            //判断必要信息是否为空
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(deviceId) || StringUtils.isBlank(userId)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String deviceUnique = String.format("%s%s%04d",projectId,"2",Integer.parseInt(deviceId));
            //LOG.info("【C#人脸识别IOT开门】参数:projectId:"+projectId+",deviceId:"+deviceId+",userId:"+userId+",deviceUnique:"+deviceUnique);

            CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
            //查询项目远程开门配置是否为启用 关闭则直接返回
            Integer networkOpen = iAppProjectServiceClient.getNetworkOpenSetting(projectId);
            if(DataStatusEnum.DELETE.getType()==networkOpen){
                return new MessageVO(AppErrorCodeEnum.CLOUD_ENTRANCE_NETWORK_OPEN_IS_CLOSED.getErrorCode());
            }
            //查询门禁设备的iot账号及绑定的iot产品key
            Map<String,Object> entrance = iCloudEntranceServiceClient.getMainDeviceUniqueAndProductKey(deviceUnique);
            Map<String,Object> result = new HashMap<>();
            if(entrance != null && entrance.get("deviceUnique") != null) {
                //LOG.info("【C#人脸识别IOT开门】进行中");
                iCloudEntranceServiceClient.wippenOpenOrCloseCtrl("itlong", entrance.get("deviceUnique").toString(),
                        Integer.valueOf(deviceUnique.substring(deviceUnique.length() - 4, deviceUnique.length())).toString(),
                        CloudEntranceOpenTypeEnum.OPEN.getType().toString(), "1", entrance.get("productKey").toString(), userId,IotOpenDoorSourceEnum.ITLONG_C_FACE.getType().toString(),
                        null,null, correlationId.getId(),"0",null);
            }

            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),result);
        } catch (Exception e) {
            throw new DataAccessException("【C#人脸识别】IOT开门失败", e);
        }
    }

    /**
     * <desc>
     *      人脸下发失败回调
     * <desc/>
     *
     * @param projectId 项目编号
     * @param faceFailDesc  下发失败原因描述(中文)
     * @param userId  人脸识别后的faceId
     * @return 标准格式化响应结果
     * @author Juguang.S
     * @createDate 2019/11/12
     */
    @PostMapping(path = "/faceFailCallback")
    @ResponseBody
    public MessageVO faceFailCallback(String projectId, String faceFailDesc,String userId) {
        try {
            //判断必要信息是否为空
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(userId)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            iSmartCardUserInfoServiceClient.faceFailCallback(projectId,faceFailDesc,userId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【C#人脸识别】人脸下发失败回调", e);
        }
    }


    /**
     * <desc>
     *      上传图片文件
     * <desc/>
     *
     * @param imageStr    图片二进制
     * @param imageType   图片类型
     * @param fileCatalog FTP业务文件夹
     * @return 图片url
     * @author wangzhi
     * @createDate 2019/03/18
     */
    private String uploadImageFile(String imageStr, String imageType, FileCatalogEnum fileCatalog) {
        try {
            imageStr = URLDecoder.decode(imageStr, "UTF-8");
        } catch (Exception e) {
            LOG.info("imageStr URLDecoder失败", e);
            return null;
        }
        byte[] bytes = null;
        try {
            bytes = new BASE64Decoder().decodeBuffer(imageStr);
        } catch (IOException e) {
            LOG.info("BASE64Decoder().decodeBuffer失败,imageStr不合法", e);
            return null;
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                byteArrayInputStream,
                imageType,
                FILE_ACCESS_URL,
                fileCatalog.getType()
        );
        try {
            //LOG.info("正在上传图片");
            Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
            //LOG.info("图片上传完毕");
            String returnCode = resultMap.get("returnCode").toString();
            if ("true".equals(returnCode)) {
                String fileUrl = resultMap.get("accessPath").toString();
                return fileUrl;
            } else {
                LOG.info(String.format("图片上传失败，returnCode: %s", returnCode));
                return null;
            }
        } catch (IOException e) {
            LOG.info("UploadFileUtil.uploadFile失败", e);
            return null;
        }
    }

    /**
     * <desc>
     *      增量获取变更数据接口
     * </desc>
     *
     * @param projectId 项目编号
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/03/18
     */
    @PostMapping(path = "/getIncrementUpdate")
    @ResponseBody
    public MessageVO getIncrementUpdateData(String projectId){
        try {
            if (StringUtils.isBlank(projectId)) {
                return new MessageVO(SmartCardErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            List<SmartCardIncrementUpdateGetVO> smartCardIncrementUpdateGetVOS = iPadFaceSyncDataServiceClient.getIncrementUpdateSmartCard(projectId);
            ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(projectId);

            List<Map<String, String>> deviceEndTime = iSmartCardFaceServiceClient.getDeviceCloudServiceCostEndTime(projectId);
            Map<String,Object> map = new HashMap<>();
            map.put("isFaceRecognition",projectPO.getIsFaceRecognition());
            map.put("syncTime",null == projectPO.getSystemDataTime() ? 10:projectPO.getSystemDataTime());
            map.put("deviceEndTimeByNew",deviceEndTime == null ? "" : deviceEndTime);
            map.put("deviceEndTime","");
            map.put("syncData",smartCardIncrementUpdateGetVOS);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
        } catch (Exception e) {
            throw new DataAccessException("【一卡通动态人脸识别】增量获取变更数据失败", e);
        }
    }

    /**
     * <desc>
     *      修改同步状态为同步结束
     * </desc>
     *
     * @param syncSerialNo 同步流水号，多个用英文逗号相连
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/03/18
     */
    @PostMapping(path = "/updateSyncStatus")
    @ResponseBody
    public MessageVO updateSyncStatus(String syncSerialNo){
        try {
            if (StringUtils.isBlank(syncSerialNo)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            iPadFaceSyncDataServiceClient.updateSyncStatusSmartCard(syncSerialNo);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【一卡通动态人脸识别】修改平板同步数据同步状态失败", e);
        }
    }

    /**
     * <desc>
     *      校验设备
     * <desc/>
     *
     * @param projectId 项目编号
     * @param deviceId  设备Id
     * @param deviceType 设备类型 1代表电梯 2代表门禁
     * @return 标准格式化响应结果
     * @author Juguang.S
     * @createDate 2019/04/15
     */
    @PostMapping(path = "/checkDevice")
    @ResponseBody
    public MessageVO checkDevice(String projectId, String deviceId, String deviceType) {
        try {
            //判断必要信息是否为空
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(deviceId) || StringUtils.isBlank(deviceType)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }

            String status = null;//设备状态
            //判断项目下是否有此设备,是否被禁用
            // 梯控
            if ("1".equals(deviceType)) {
                status = iAppPadFaceServiceClient.elevatorAuthorityCheck(projectId, deviceId, "", "");
            }
            //门禁
            else if ("2".equals(deviceType)) {
                status = iAppPadFaceServiceClient.entranceAuthorityCheck(projectId, deviceId, "");
            }
            //返回空则无此设备
            if (status == null || "".equals(status)) {
                return new MessageVO(AppErrorCodeEnum.PAD_DEVICE_NOT_EXISTS.getErrorCode());
            }
            //设备禁用
            if ("2".equals(status)) {
                return new MessageVO(AppErrorCodeEnum.PAD_DEVICE_FORBIDDEN.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【C#人脸识别】校验设备失败", e);
        }
    }

}
